namespace SimpleWebServices.Web
{
    using System;
    using System.Xml;
    using SimpleWebServices;
    using Xunit;

    public sealed class ExpirationFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<Expiration>()
                .DerivesFrom<object>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new Expiration());
        }

        [Fact]
        public void ctor_string()
        {
            Assert.NotNull(new Expiration("P1D"));
        }

        [Fact]
        public void ctor_stringEmpty()
        {
            Assert.NotNull(new Expiration(string.Empty));
        }

        [Fact]
        public void ctor_stringNull()
        {
            Assert.NotNull(new Expiration(null as string));
        }

        [Fact]
        public void prop_Value()
        {
            Assert.True(new PropertyExpectations(typeof(Expiration).GetProperty("Value"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void opImplicit_DateTime_Expiration()
        {
            DateTime expected = DateTime.UtcNow.AddDays(1);
            DateTime actual = new Expiration(XmlConvert.ToString(expected, XmlDateTimeSerializationMode.Utc));

            Assert.Equal<DateTime>(expected, actual);
        }

        [Fact]
        public void opImplicit_DateTime_ExpirationNull()
        {
            DateTime expected = DateTime.MinValue;
            DateTime actual = null as Expiration;

            Assert.Equal<DateTime>(expected, actual);
        }

        [Fact]
        public void opImplicit_Expiration_DateTime()
        {
            DateTime value = DateTime.UtcNow;

            Expiration expected = new Expiration(XmlConvert.ToString(value, XmlDateTimeSerializationMode.Utc));
            Expiration actual = value;

            Assert.Equal<Expiration>(expected, actual);
        }

        [Fact]
        public void opImplicit_Expiration_TimeSpan()
        {
            TimeSpan value = new TimeSpan(1, 2, 3);

            Expiration expected = new Expiration(XmlConvert.ToString(value));
            Expiration actual = value;

            Assert.Equal<Expiration>(expected, actual);
        }

        [Fact]
        public void opImplicit_Expiration_string()
        {
            string value = "P1D";

            Expiration expected = new Expiration(value);
            Expiration actual = value;

            Assert.Equal<Expiration>(expected, actual);
        }

        [Fact]
        public void opImplicit_Expiration_stringNull()
        {
            string value = null;

            Expiration expected = null;
            Expiration actual = value;

            Assert.Equal<Expiration>(expected, actual);
        }

        [Fact]
        public void opImplicit_string_Expiration()
        {
            string expected = "P1D";
            string actual = new Expiration(expected);

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void opImplicit_string_ExpirationNull()
        {
            string expected = null;
            string actual = null as Expiration;

            Assert.Equal<string>(expected, actual);
        }

        [Fact]
        public void op_ToDateTime()
        {
            DateTime expected = DateTime.MinValue;
            DateTime actual = new Expiration().ToDateTime();

            Assert.Equal<DateTime?>(expected, actual);
        }

        [Fact]
        public void op_ToDateTime_whenValueEmpty()
        {
            DateTime expected = DateTime.MinValue;
            DateTime actual = new Expiration(string.Empty).ToDateTime();

            Assert.Equal<DateTime?>(expected, actual);
        }

        [Fact]
        public void op_ToDateTime_whenValueTimeSpanOneDay()
        {
            try
            {
                DateTimeFactory.Mock = DateTime.UtcNow;

                string expected = DateTimeFactory.UtcNow.AddDays(364).ToString("r");
                string actual = new Expiration("P364D").ToDateTime().ToString("r");

                Assert.Equal<string>(expected, actual);
            }
            finally
            {
                DateTimeFactory.Reset();
            }
        }

        [Fact]
        public void op_ToDateTime_whenValueAbsoluteDate()
        {
            DateTime expected = DateTime.UtcNow.AddDays(1);
            DateTime actual = new Expiration(XmlConvert.ToString(expected, XmlDateTimeSerializationMode.Utc)).ToDateTime();

            Assert.Equal<DateTime>(expected, actual);
        }
    }
}